#include "ZImage.h"
#include <Tools/ZLogManager.h>
#include <Tools/ConfigManager.h>
#include <string>
//#include "../MachineLearning/ImageFeature.h"

GLOBAL_NAMESPACE_BEGIN

namespace ImageSpace
{
    static const std::string templateImagePrefix("templ");
    static const std::string templateImageFolder("templFolder");
    static const std::string maskImagePrefix("mask");
    static const std::string maskImageFolder("maskFolder");

    static void generateTemplateImageNames(ImageSpace::Image* ima, ImageSpace::Image* templateImg, const std::string& outFolder)
    {
        std::string name = ima->getName();
        std::string prefix, folder;
        prefix = ConfigManager::getSingletonPtr()->getConfig()->read(templateImagePrefix, prefix);
        templateImg->setName(prefix + name);
        folder = ConfigManager::getSingletonPtr()->getConfig()->read(templateImageFolder, folder);
        templateImg->setFullPath(outFolder + folder + prefix + name);
    }

    static void generateMaskImaegNames(ImageSpace::Image* ima, ImageSpace::Image* mask, const std::string& outFolder)
    {
        std::string name = ima->getName();
        std::string prefix, folder;
        prefix = ConfigManager::getSingletonPtr()->getConfig()->read(maskImagePrefix, prefix);
        mask->setName(prefix + name);
        folder = ConfigManager::getSingletonPtr()->getConfig()->read(maskImageFolder, folder);
        mask->setFullPath(outFolder + folder + prefix + name);
    }

    Image::Image(const ImageType type, Image* refIma, const std::string& outFolder)
        : type_(type)
    {
        if (refIma)
        {
            if (type == IMAGE_Template)
                generateTemplateImageNames(refIma, this, outFolder);
            else if (type == IMAGE_Mask)
                generateMaskImaegNames(refIma, this, outFolder);
        }
    }

    Image::~Image()
    {
    }

    bool Image::loadImageFromFile(const char* fileName)
    {
        data_ = cv::imread(fileName, CV_LOAD_IMAGE_GRAYSCALE);
        //DefaultLog << "Image File: " << fileName << " has loaded.";
        std::string name(fileName);
        imageName_ = name.substr(name.find_last_of("/\\")+1);
        imageFullPath_ = name;
        //DefaultLog << " image Name: " << imageName_;
        return true;
    }

    bool Image::saveImageToFile(const char* fileName)
    {
        return cv::imwrite(fileName, data_);
    }

    size_t Image::getDimension()
    {
        return data_.rows * data_.cols;
    }

    void Image::getData(double* dest)
    {
        int count = 0;
        for (int x = 0; x < data_.rows; x++)
        {
            for (int y = 0; y < data_.cols; y++)
            {
                dest[count++] = (double)data_.at<uchar>(x, y)/255.0;
            }
        }
    }

    cv::Mat* Image::getData()
    {
        return &data_;
    }

    const cv::Mat* Image::getData() const
    {
        return &data_;
    }

    std::string Image::getName()
    {
        return imageName_;
    }

    const std::string Image::getName() const
    {
        return imageName_;
    }

    std::string Image::getFullPath()
    {
        return imageFullPath_;
    }

    const std::string Image::getFullPath() const
    {
        return imageFullPath_;
    }

    Image::ImageType Image::getType()
    {
        return type_;
    }

    const Image::ImageType Image::getType() const
    {
        return type_;
    }

    void Image::setType(Image::ImageType type)
    {
        type_ = type;
    }

    void Image::setData(const cv::Mat& data)
    {
        data_ = data;
    }

    void Image::setName(const std::string& name)
    {
        imageName_ = name;
    }
    
    void Image::setFullPath(const std::string& fullname)
    {
        imageFullPath_ = fullname;
    }

    void Image::setId(int id)
    {
        id_ = id;
    }

    int Image::getId()
    {
        return id_;
    }

    int Image::getId() const
    {
        return id_;
    }

    Image* Image::resize(int width, int height)
    {
        if (data_.empty())
            return NULL;

        Image* retImg = new Image;
        cv::Mat newMat;
        cv::resize(data_, newMat, cv::Size(width, height));
        retImg->setData(newMat);
        std::stringstream ss;
        std::string extName = imageName_.substr(imageName_.find_last_of("."));
        ss  << imageName_.substr(0, imageName_.find_last_of("."))
            << "_" << width << "_" << height << extName;
        retImg->setName(ss.str());
        return retImg;
    }

    void Image::modifyTheName()
    {
        std::string oldName = getName();
        std::string oldFullPath = getFullPath();
        std::stringstream ss;
        switch (getType())
        {
        case IMAGE_Default:
            break;
        case IMAGE_Template:
        case IMAGE_Mask:
            ss << oldName.substr(0, oldName.find_last_of("."))
                << "_" << getId() << oldName.substr(oldName.find_last_of("."));
            setName(ss.str());
            ss.str("");
            ss << oldFullPath.substr(0, oldFullPath.find_last_of("."))
                << "_" << getId() << oldFullPath.substr(oldFullPath.find_last_of("."));
            setFullPath(ss.str());
            break;
        }
    }

    //void Image::setFeature(MLAlgorithms::ImageFeature* feature)
    //{
    //    feature_ = feature;
    //}
}

GLOBAL_NAMESPACE_END